#include <usart.h>

#ifdef __USART_SUPPORT_PRINTF__
#include <stdarg.h> // 可变参数支持
#include <stdio.h>
#endif

/* 函数作用：串口1初始化
 * 参数说明：
 * bound：串口波特率
 * 返回值：void
 */
void usart1_init(u32 bound)
{
    GPIO_InitTypeDef GPIO_InitStrue;
    USART_InitTypeDef USART_InitStrue;
    NVIC_InitTypeDef NVIC_InitStrue;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); // 使能相应的GPIO、串口

    GPIO_InitStrue.GPIO_Mode  = GPIO_Mode_AF_PP; // 复用推挽输出
    GPIO_InitStrue.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStrue.GPIO_Speed = GPIO_Speed_10MHz;

    GPIO_Init(GPIOA, &GPIO_InitStrue);

    GPIO_InitStrue.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
    GPIO_InitStrue.GPIO_Pin  = GPIO_Pin_10;

    GPIO_Init(GPIOA, &GPIO_InitStrue);

    USART_InitStrue.USART_BaudRate            = bound;                          // 波特率
    USART_InitStrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控
    USART_InitStrue.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;  // 串口模式
    USART_InitStrue.USART_Parity              = USART_Parity_No;                // 奇偶校验
    USART_InitStrue.USART_StopBits            = USART_StopBits_1;               // 停止位
    USART_InitStrue.USART_WordLength          = USART_WordLength_8b;            // 数据字长

    USART_Init(USART1, &USART_InitStrue); // 串口初始化
    USART_Cmd(USART1, ENABLE);            // 串口使能

    NVIC_InitStrue.NVIC_IRQChannel                   = USART1_IRQn; // 中断类型，定义在文件stm32f10x.h中170行处
    NVIC_InitStrue.NVIC_IRQChannelCmd                = ENABLE;      // 使能
    NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority = 1;           // 抢占优先级
    NVIC_InitStrue.NVIC_IRQChannelSubPriority        = 1;           // 响应优先级

    NVIC_Init(&NVIC_InitStrue);                    // 设置中断抢占优先级与响应优先级
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接收中断
}

#ifdef __USART_SUPPORT_PRINTF__
/* 函数作用：格式化输出到串口
 * 参数说明：
 * USARTx：选择 USART 或 UART 外设。
 *         此参数可以是以下值之一：
 *         USART1、USART2、USART3、UART4 或 UART5。
 * format：格式化控制字符串
 * 返回值：void
 */
void USART_printf(USART_TypeDef *USARTx, const char *format, ...)
{
    u16 i;
    char buff[FORMAT_STRING_LENGTH]; // 用于存储格式化后的字符串
    va_list ap;

    va_start(ap, format);
    vsnprintf(buff, FORMAT_STRING_LENGTH, format, ap);
    va_end(ap);

    for (i = 0; (buff[i] != '\0') && (i < FORMAT_STRING_LENGTH); i++)
    {
        USART_SendData(USARTx, buff[i]);

        // 等待发送完成
        while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)
            ;
    }
}
#endif

/* 函数作用：串口1中断服务函数
            函数名固定，具体函数名在启动文件（汇编文件）中查找
 * 参数说明：void
 * 返回值：void
 */
void USART1_IRQHandler(void)
{
    u8 data;

    if (USART_GetITStatus(USART1, USART_IT_RXNE))
    {
        data = USART_ReceiveData(USART1);
        USART_SendData(USART1, data);
    }
}
